
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">















 
 
 
 
 
 
 
  
  


<html>
  <head>
    <script type="text/javascript" language="JavaScript">
    ORIGINAL_PAGE_PATH = "/appengine/articles/app-engine-patch.html";
    </script>
    
    
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Unleash Django with app-engine-patch - Google App Engine - Google Code</title>
<script type="text/javascript"><!--
(function(){function a(){this.t={};this.tick=function(c){this.t[c]=(new Date).getTime()};this.tick("start")}var b=new a;window.jstiming={Timer:a,load:b};if(window.external&&window.external.pageT)window.jstiming.pt=window.external.pageT;})();

var _tocPath_ = '/appengine/docs/_toc.ezt';
var codesite_token = null;
//--></script>
<link href="../../css/codesite.pack.04102009.css" type="text/css" rel="stylesheet"></link>
<script src="../../js/codesite_head.pack.04102009.js" type="text/javascript"></script>
<script type="text/javascript">CODESITE_CSITimer['load'].tick('bhs');</script>
<link rel="search" type="application/opensearchdescription+xml" title="Google Code" href="http://code.google.com/osd.xml" />

<!--[if IE]><link rel="stylesheet" type="text/css" href="../../css/iehacks.css" /><![endif]-->

    <link href="../../css/semantic_headers.css" rel="stylesheet" type="text/css" />
    <link href="../css/local_extensions.css" rel="stylesheet" type="text/css" />
  </head>

  <body class="gc-documentation">

    
    
    
</a>

<div id="gb">
 <span>
  
    <a id="lang-dropdown" class="dropdown" href="http://code.google.com" onclick="return false;"><img class="globeicon" src="../../images/globe2_small.png"/><span>English</span></a>
  
 </span>
</div>

<div class="gbh" style="left: 0pt;"></div>
<div class="gbh" style="right: 0pt;"></div>


<style type="text/css">
  #gc-topnav h1 {
    padding: 0 0 0 6px;
  }
</style>


<div id="gc-container">
<a name="top"></a>
<div id="skipto">
  <a href="#gc-pagecontent-anchor">Skip to page content</a>
  <a href="#gc-toc-anchor">Skip to main navigation</a>
</div>

<div id="gc-header">
  <div id="logo"><a href="http://code.google.com">
  
  
     <img src="../../images/cleardot.gif" height="1px" width="1px" alt="Google Code Home Page" id="gc-logo-img"/>
  
  
  </a></div>
  <div id="search">
    <div id="searchForm" class="searchForm">
      <form id="cse" action="http://www.google.com/cse" accept-charset="utf-8" class="gsc-search-box" onsubmit="executeGSearch(document.getElementById('gsearchInput').value); return false;">
      <noscript>
      <input type="hidden" name="cref" value="http://code.google.com/cse/googlecode-context.xml"/>
      </noscript>
        <table class="gsc-search-box" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td class="gsc-input">
                <input id="gsearchInput" type="text" name="q" maxlength="2048" class="gsc-input" autocomplete="off" title="Google Code Search" style="width:345px"/>
              </td>
              <td class="gsc-search-button">
                <div id="cs-searchresults" onclick="event.cancelBubble = true;"></div>
                <input title="Search" id="gsearchButton" class="gsc-search-button" name="sa" value="Search" type="submit"/>
              </td>
            </tr>
            <tr>
              <td colspan="2" class="greytext">e.g. "templates" or "datastore"</td>
            </tr>
          </tbody>
        </table>
      </form>
    </div> <!-- end searchForm -->
  </div> <!-- end search -->
</div> <!-- end gc-header -->


<div id="codesiteContent">

<a name="gc-topnav-anchor"></a>
<div id="gc-topnav">
  <h1>Google App Engine</h1>
  <ul id="articles" class="gc-topnav-tabs">

    <li id="home_link">
      <a href="../index.html" title="Google App Engine home page">Home</a>
    </li>
  
    <li id="docs_link">
      <a href="../docs/index.html" title="Official Google App Engine documentation">Docs</a>
    </li>
  
    <li id="faq_link">
      <a href="../kb/index.html" title="Answers to frequently asked questions about Google App Engine">FAQ</a>
    </li>
  
    <li id="articles_link">
      <a href="index.html" class="selected" title="Focused articles and tutorials for Google App Engine developers">Articles</a>
    </li>
  
    <li>
      <a href="http://googleappengine.blogspot.com/" title="Official Google App Engine blog">Blog</a>
    </li>
  
    <li>
      <a href="../community.html" title="Community home for Google App Engine">Community</a>
    </li>
  
    <li>
      <a href="../terms.html" title="Google App Engine terms of service">Terms</a>
    </li>
  
    <li>
      <a href="../downloads.html" title="Download Google App Engine">Download</a>
    </li>
  

  </ul>
</div> <!-- end gc-topnav -->

    <div class="g-section g-tpl-170">

      <a name="gc-toc-anchor"></a>  
      <div class="g-unit g-first" id="gc-toc">
        <ul>
  <li><a href="../downloads.html">Downloads</a></li>
  <li><a href="http://code.google.com/status/appengine">System Status</a></li>
  <li><a href="http://code.google.com/p/googleappengine/issues/list">Issue Tracker</a></li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Getting Started</h2>
    <ul>
      <li><a href="../docs/whatisgoogleappengine.html">What Is Google App Engine?</a></li>
      <li><a href="../docs/java/gettingstarted/index.html">Java</a>
        <ul>
              <li><a href="../docs/java/gettingstarted/introduction.html">Introduction</a></li>
    <li><a href="../docs/java/gettingstarted/installing.html">Installing the Java SDK</a></li>
    <li><a href="../docs/java/gettingstarted/creating.html">Creating a Project</a></li>
    <li><a href="../docs/java/gettingstarted/usingusers.html">Using the Users Service</a></li>
    <li><a href="../docs/java/gettingstarted/usingjsps.html">Using JSPs</a></li>
    <li><a href="../docs/java/gettingstarted/usingdatastore.html">Using the Datastore with JDO</a></li>
    <li><a href="../docs/java/gettingstarted/staticfiles.html">Using Static Files</a></li>
    <li><a href="../docs/java/gettingstarted/uploading.html">Uploading Your Application</a></li>

        </ul>
      </li>
      <li><a href="../docs/python/gettingstarted/index.html">Python</a>
        <ul>
            <li><a href="../docs/python/gettingstarted/introduction.html">Introduction</a></li>
  <li><a href="../docs/python/gettingstarted/devenvironment.html">The Development Environment</a></li>
  <li><a href="../docs/python/gettingstarted/helloworld.html">Hello, World!</a></li>
  <li><a href="../docs/python/gettingstarted/usingwebapp.html">Using the webapp Framework</a></li>
  <li><a href="../docs/python/gettingstarted/usingusers.html">Using the Users Service</a></li>
  <li><a href="../docs/python/gettingstarted/handlingforms.html">Handling Forms With webapp</a></li>
  <li><a href="../docs/python/gettingstarted/usingdatastore.html">Using the Datastore</a></li>
  <li><a href="../docs/python/gettingstarted/templates.html">Using Templates</a></li>
  <li><a href="../docs/python/gettingstarted/staticfiles.html">Using Static Files</a></li>
  <li><a href="../docs/python/gettingstarted/uploading.html">Uploading Your Application</a></li>

        </ul>
      </li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Java <sup class="new">Early Look</sup></h2>
    <ul>
          <li><a href="../docs/java/overview.html">Overview</a></li>
    <li><a href="../docs/java/runtime.html">Servlet Environment</a></li>
    <li><a href="../docs/java/datastore/index.html">Storing Data</a>
      <ul>
            <li><a href="../docs/java/datastore/overview.html">Overview</a></li>
    <li><a href="../docs/java/datastore/usingjdo.html">Using JDO</a></li>
    <li><a href="../docs/java/datastore/dataclasses.html">Defining Data Classes</a></li>
    <li><a href="../docs/java/datastore/creatinggettinganddeletingdata.html">Creating, Getting and Deleting Data</a></li>
    <li><a href="../docs/java/datastore/queriesandindexes.html">Queries and Indexes</a></li>
    <li><a href="../docs/java/datastore/transactions.html">Transactions</a></li>
    <li><a href="../docs/java/datastore/relationships.html">Relationships</a></li>
    <li><a href="../docs/java/datastore/usingjpa.html">Using JPA</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/datastore/package-summary.html">Low-level API</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/apis.html">Services</a>
      <ul>
        <li><a href="../docs/java/memcache/index.html">Memcache</a>
          <ul>
                <li><a href="../docs/java/memcache/overview.html">Overview</a></li>
    <li><a href="../docs/java/memcache/usingjcache.html">Using JCache</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/memcache/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/urlfetch/index.html">URL Fetch</a>
          <ul>
                <li><a href="../docs/java/urlfetch/overview.html">Overview</a></li>
    <li><a href="../docs/java/urlfetch/usingjavanet.html">Using java.net</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/urlfetch/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/mail/index.html">Mail</a>
          <ul>
                <li><a href="../docs/java/mail/overview.html">Overview</a></li>
    <li><a href="../docs/java/mail/usingjavamail.html">Using JavaMail</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/mail/package-summary.html">Low-level API</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/images/index.html">Images</a>
          <ul>
                <li><a href="../docs/java/images/overview.html">Overview</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/images/package-summary.html">API Reference</a></li>

          </ul>
        </li>
        <li><a href="../docs/java/users/index.html">Google Accounts</a>
          <ul>
                <li><a href="../docs/java/users/overview.html">Overview</a></li>
    <li><a href="../docs/java/javadoc/com/google/appengine/api/users/package-summary.html">API Reference</a></li>

          </ul>
        </li>
      </ul>
    </li>
    <li><a href="../docs/java/javadoc/index.html">Javadoc Reference</a></li>
    <li><a href="../docs/java/jrewhitelist.html">JRE Class White List</a></li>
    <li><a href="../docs/java/config/index.html">Configuration</a>
      <ul>
            <li><a href="../docs/java/config/webxml.html">Deployment Descriptor</a></li>
    <li><a href="../docs/java/config/appconfig.html">App Config</a></li>
    <li><a href="../docs/java/config/indexconfig.html">Index Config</a></li>
    <li><a href="../docs/java/config/cron.html">Scheduled Tasks</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/tools/index.html">Tools</a>
      <ul>
            <li><a href="../docs/java/tools/devserver.html">Development Server</a></li>
    <li><a href="../docs/java/tools/uploadinganapp.html">Uploading and Managing</a></li>
    <li><a href="../docs/java/tools/eclipse.html">Google Plugin for Eclipse</a></li>
    <li><a href="../docs/java/tools/ant.html">Using Apache Ant</a></li>

      </ul>
    </li>
    <li><a href="../docs/java/howto/index.html">How-To</a>
      <ul>
              <li><a href="../docs/java/howto/unittesting.html">Unit Testing</a></li>

      </ul>
    </li>

    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Python</h2>
    <ul>
          <li><a href="../docs/python/overview.html">Overview</a></li>
    <li><a href="../docs/python/runtime.html">CGI Environment</a></li>
    <li><a href="../docs/python/datastore/index.html">Storing Data</a>
      <ul>
             <li><a href="../docs/python/datastore/overview.html">Overview</a></li>
     <li><a href="../docs/python/datastore/entitiesandmodels.html">Entities and Models</a></li>
     <li><a href="../docs/python/datastore/creatinggettinganddeletingdata.html">Creating, Getting and Deleting Data</a></li>
     <li><a href="../docs/python/datastore/keysandentitygroups.html">Keys and Entity Groups</a></li>
     <li><a href="../docs/python/datastore/queriesandindexes.html">Queries and Indexes</a></li>
     <li><a href="../docs/python/datastore/transactions.html">Transactions</a></li>
     <li><a href="../docs/python/datastore/typesandpropertyclasses.html">Types and Property Classes</a></li>
     <li><a href="../docs/python/datastore/gqlreference.html">GQL Reference</a></li>

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/datastore/modelclass.html">Model</a></li>
         <li><a href="../docs/python/datastore/expandoclass.html">Expando</a></li>
         <li><a href="../docs/python/datastore/polymodelclass.html">PolyModel</a></li>
         <li><a href="../docs/python/datastore/propertyclass.html">Property</a></li>
         <li><a href="../docs/python/datastore/queryclass.html">Query</a></li>
         <li><a href="../docs/python/datastore/gqlqueryclass.html">GqlQuery</a></li>
         <li><a href="../docs/python/datastore/keyclass.html">Key</a></li>
         <li><a href="../docs/python/datastore/functions.html">Functions</a></li>
         <li><a href="../docs/python/datastore/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

      </ul>
    </li>
    <li><a href="../docs/python/apis.html">Services</a>
      <ul>
        <li><a href="../docs/python/memcache/index.html">Memcache</a>
          <ul>
                 <li><a href="../docs/python/memcache/overview.html">Overview</a></li>
      <li><a href="../docs/python/memcache/usingmemcache.html">Using Memcache</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/memcache/clientclass.html">Client</a></li>
         <li><a href="../docs/python/memcache/functions.html">Functions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/urlfetch/index.html">URL Fetch</a>
          <ul>
                 <li><a href="../docs/python/urlfetch/overview.html">Overview</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/urlfetch/fetchfunction.html">The fetch Function</a></li>
         <li><a href="../docs/python/urlfetch/responseobjects.html">Response Objects</a></li>
         <li><a href="../docs/python/urlfetch/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/mail/index.html">Mail</a>
          <ul>
                 <li><a href="../docs/python/mail/overview.html">Overview</a></li>
     <li><a href="../docs/python/mail/sendingmail.html">Sending Mail</a></li>
     <li><a href="../docs/python/mail/attachments.html">Attachments</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/mail/emailmessageclass.html">EmailMessage</a></li>
         <li><a href="../docs/python/mail/emailmessagefields.html">Message Fields</a></li>
         <li><a href="../docs/python/mail/functions.html">Functions</a></li>
         <li><a href="../docs/python/mail/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/images/index.html">Images</a>
          <ul>
                 <li><a href="../docs/python/images/overview.html">Overview</a></li>
     <li><a href="../docs/python/images/installingPIL.html">Installing PIL</a></li>
     <li><a href="../docs/python/images/usingimages.html">Using the Images API</a></li>
     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/images/imageclass.html">Image</a></li>
         <li><a href="../docs/python/images/functions.html">Functions</a></li>
         <li><a href="../docs/python/images/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
        <li><a href="../docs/python/users/index.html">Google Accounts</a>
          <ul>
                 <li><a href="../docs/python/users/overview.html">Overview</a></li>
     <li><a href="../docs/python/users/userobjects.html">User Objects</a></li>
     <li><a href="../docs/python/users/loginurls.html">Login URLs</a></li>
     <li><a href="../docs/python/users/adminusers.html">Admin Users</a></li>

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/users/userclass.html">User</a></li>
         <li><a href="../docs/python/users/functions.html">Functions</a></li>
         <li><a href="../docs/python/users/exceptions.html">Exceptions</a></li>
       </ul>
     </li>

          </ul>
        </li>
      </ul>
    </li>
    <li><a href="../docs/python/config/index.html">Configuration</a>
      <ul>
            <li><a href="../docs/python/config/appconfig.html">App Config</a></li>
    <li><a href="../docs/python/config/indexconfig.html">Index Config</a></li>
    <li><a href="../docs/python/config/cron.html">Scheduled Tasks</a></li>

      </ul>
    </li>
    <li><a href="../docs/python/tools/index.html">Tools</a>
      <ul>
            <li><a href="../docs/python/tools/devserver.html">Development Server</a></li>
    <li><a href="../docs/python/tools/uploadinganapp.html">Uploading and Managing</a></li>
    <li><a href="../docs/python/tools/uploadingdata.html">Uploading Data</a></li>
    <li><a href="../docs/python/tools/webapp/index.html">webapp Framework</a>
      <ul>
             <li><a href="../docs/python/tools/webapp/overview.html">Overview</a></li>
     <li><a href="../docs/python/tools/webapp/running.html">Running the Application</a></li>
     <li><a href="../docs/python/tools/webapp/requesthandlers.html">Request Handlers</a></li>
     <li><a href="../docs/python/tools/webapp/requestdata.html">Request Data</a></li>
     <li><a href="../docs/python/tools/webapp/buildingtheresponse.html">Building the Response</a></li>
     <li><a href="../docs/python/tools/webapp/redirects.html">Redirects, Headers and Status Codes</a></li>
     

     <li><span class="tlw-title tlw-expanded">Reference</span>
       <ul>
         <li><a href="../docs/python/tools/webapp/requestclass.html">Request</a></li>
         <li><a href="../docs/python/tools/webapp/responseclass.html">Response</a></li>
         <li><a href="../docs/python/tools/webapp/requesthandlerclass.html">RequestHandler</a></li>
         <li><a href="../docs/python/tools/webapp/wsgiapplicationclass.html">WSGIApplication</a></li>
         <li><a href="../docs/python/tools/webapp/utilmodule.html">Utility Functions</a></li>
         
       </ul>
     </li>

      </ul>
    </li>
    <li><a href="../docs/python/tools/libraries.html">Third-party Libraries</a></li>

      </ul>
    </li>
    <li><a href="../docs/python/howto/index.html">How-To</a>
      <ul>
              <li><a href="../docs/python/howto/usinggdataservices.html">Google Data Services</a></li>

      </ul>
    </li>

    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Managing Your App</h2>
    <ul>
      <li><a href="../docs/theadminconsole.html">The Admin Console</a></li>
      <li><a href="../docs/quotas.html">Quotas</a></li>
      <li><a href="../docs/billing.html">Billing</a></li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><h2>Resources</h2>
    <ul>
      <li><a href="../kb/index.html">FAQ</a></li>
      <li><a href="index.html">Articles</a></li>
      <li><a href="http://appengine-cookbook.appspot.com/">Cookbook</a></li>
      <li><a href="http://appgallery.appspot.com/">App Gallery</a></li>
      <li><a href="http://code.google.com/p/googleappengine/">SDK Code</a></li>
      <li><a href="http://code.google.com/p/google-app-engine-samples/">Sample Apps Code</a></li>
      <li><a href="../community.html">Discussion Groups</a></li>
    </ul>
  </li>
</ul>
<div class="line"></div>
<ul>
  <li><a href="../docs/roadmap.html">Product Roadmap</a></li>
  <li><a href="http://code.google.com/p/googleappengine/wiki/SdkReleaseNotes">Release Notes</a></li>
  <li><a href="../docs/revision_history.html">Revision History</a></li>
</ul>

        <a class="hidden" href="#gc-topnav-anchor">More Google App Engine resource links</a>
      </div>
      
      <a name="gc-pagecontent-anchor"></a>   
      <div class="g-unit" id="gc-pagecontent">
        <script type="text/javascript">CODESITE_docEarlyProcessing();</script>
        <h1 class="page_title">Unleash Django with app-engine-patch</h1>


<p class="note">This article was written and submitted by an external
developer. The Google App Engine team thanks Jesaja Everling for his time and
expertise.</p>
<p><i>Jesaja Everling</i><br>
<i>February 2009</i>
</p>
<div id="jd-content">
<div class="jd-descr"> 
<h2>Introduction</h2>
<p>The Django framework can make your life as a web developer a lot easier. It
takes care of a lot of common problems web developers have to deal with, and
offers many "reusable apps" - battle tested pieces of code that you can plug
into your project.</p>
<p>Because of a few conceptual differences, several Django features do not
work out of the box with Google App Engine.&nbsp; One of the main features
that doesn't work with App Engine is the Django ORM, since the App Engine
Datastore differs from a traditional relational database model off of which
the Django ORM is based. app-engine-patch is a project that aims for providing
all the functionality of Django while working around the limitations imposed
by the missing Django ORM support. The project can be found here:
http://code.google.com/p/app-engine-patch/</p>
<p>In this article, we will present a few reasons why you may want to consider
using Django and app-engine-patch for your projects, and then demonstrate the
power of app-engine-patch with a sample application. This sample will support
authentication with both Google and non-Google accounts.</p> 
<h2>Reasons for considering Django over Webapp</h2>
<p>The advantage to using Django over Google App Engine's webapp framework is
that Django has been widely in use for years, for many types of web
applications. Additionally, Django has an extensive developer community. There
are numerous blogs dealing with Django, a very frequently used mailing-list,
and the #django IRC-channel.</p>
<p>Webapp was developed exclusively for Google App Engine and has yet to build
all this sort of community backing. Django has also become the "standard"
Python web-framework. There are several other great frameworks, like Pylons or
cherrypy, most of which will also work on App Engine, but Django certainly is
the most popular one at the moment. It offers many features important for
large projects, like built-in internationalization support, caching,
authentication with sessions, support for middleware and much more. Webapp is
missing most of these features. If you need them, you have to create them
yourself. Lastly, Django makes you less dependent on App Engine. If you use
webapp, you cannot easily switch to another system, at least at the
moment.</p> 
<h2>Reasons for using app-engine-patch</h2>
<p><code>app-engine-patch</code> ports as much as possible from the Django
world to App Engine. You will be able to use a lot of the reusable apps for
Django without much adjustments. Porting existing Django code to App Engine
will also be much easier. <code>app-engine-patch</code> will also reduce the
differences between traditional Django and that used for App Engine. So if,
for whatever reason, you wish to switch from App Engine to your own hosting
solution in the future it will largely reduce the work required. And it allows
you to benefit from the support the large Django community provides.
<code>app-engine-patch</code> also ships with a library called
<code>ragendja</code> that provides even more features, including transaction
decorators and global template tags. For the full list of the features that
<code>app-engine-patch</code> provides, have a look at the project's
homepage:<a
href="http://code.google.com/p/app-engine-patch/">http://code.google.com/p/app-engine-patch/</a></p>
<p>Unlike the App Engine Helper for Django, which emulates Django models by
using a custom BaseModel, app-engine-patch sticks with the regular Datastore
API. This is due to the fact that it's not really possible to emulate the
Django models with the App Engine Datastore, and it has the advantage that you
can use new Datastore features as soon as they get released.</p>
<p><code>app-engine-patch</code> provides a number of features that the App
Engine Helper for Django is missing. Further details are available on the
project homepage. Another important difference is that app-engine-patch tries
to support the latest stable release of Django, whereas the Helper ships with
version 0.96 (the svn trunk supports version 1.0).</p>
<h2>Obtaining app-engine-patch</h2>
<p>To get you off to an easy start, <code>app-engine-patch</code> is
distributed as a self-contained sample project. You can get the latest release
on the project page here: <a
href="http://code.google.com/p/app-engine-patch/downloads/list">http://code.google.com/p/app-engine-patch/downloads/list</a>.
At the time of this writing, 0.9.3. is the latest version.</p>
<p><code>App-engine-patch</code> needs the App Engine SDK to work: <a
href="http://code.google.com/appengine/downloads.html">http://code.google.com/appengine/downloads.html</a>.</p>
<p>For Windows and Mac OS X, you just have to use the provided installer for
the SDK. If you are on Linux, put the SDK in a folder included in your PATH
environment variable or in <code>/usr/local/google_appengine</code>. Please
make sure the SDK-folder is named <code>google_appengine</code>.</p>
<p>To start the sample project, change to the
<code>appenginepatch-sample</code> folder, and execute <code>manage.py
runserver</code> from the command line. <code>app-engine-patch</code> will
start the App Engine development server behind the scenes, and you are ready
to go. If you access <code>http://localhost:8000</code> in your browser, you
will see the sample project in action. The sample demonstrates the use of some
of Django's generic views, which provide shortcuts for common tasks like
creating or editing model instances.</p> 
<h2>A practical example</h2>
<p>To demonstrate some of the features that app-engine-patch provides, we will
use Django to re-create the Guestbook application from here:
<a href="../docs/python/gettingstarted/usingdatastore.html">http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html</a>. We
will use generic views, and add user authentication for both Google and non
Google users.</p>
<p>It may initially seem that there is some overhead involved with Django's
directory organization. However, the structure is beneficial as it will help
you to keep your code organized and reusable, which is important for larger
projects.</p>
<h2>Django project structure</h2>
<p>In Django, a project is split into app packages. It is possible to create
certain app functionality in a way that make them independent of a given
project. Thus, you can plug packages into multiple Django projects. An example
of an app package would be a tagging library for a blog.</p>
<p>In addition to apps, Django projects also contain a global settings file
and a root URL-configuration file which defines how URLs are processed by the
framework. Apps can have an additional url-configuration to be included in the
main URL-configuration file. Django's templates work in a similar fashion. You
can have global templates used by all apps, and also app-specific
templates.</p>
<p>But enough of the talking, lets get some work done!</p> 
<h2>Configuring your project</h2>
<p>First, let's configure an installation of app-engine-patch so that it's
ready for deployment. Open Google App Engine's <code>app.yaml</code>
configuration file, and replace the application field with your app id. You
can execute <code>manage.py update</code> now to deploy your app to Google App
Engine.</p>
<p>If you look at the contents of the sample project, you will see that the
sample app lives in a directory called <code>myapp</code>. Let's create
another app, guestbook. Create a folder named <code>guestbook</code>, and fill
it with these files:
<ul>
<li><code>__init__.py</code> - So that Python treats this folder as a
package</li>
<li><code>urls.py</code> - For app-specific URL-configuration. It controls
which view (the request handlers) will be executed for a given URL</li>
<li><code>models.py</code> - For the data models for the app</li>
<li><code>views.py</code> - To obtain the views, which is the Django term for
the logic that processes a request</li>
<li><code>templates</code> - A folder for your HTML templates for this
app</li></ul></p>
<p>Let's install the app into our project. To do this, include the name of
your app in the list of <code>INSTALLED_APPS</code> in your
<code>settings.py</code> file:</p>
<pre class="prettyprint">
INSTALLED_APPS = (
    ...
    'guestbook',
)
</pre>
<p>If you were using Django with a relational database, you would now have to
run <code>manage.py syncdb</code> to create the necessary database tables.
With App Engine this happens on the fly.</p>
<p>Now let's hook our guestbook app into the global URL-routing. Change the
project's global <code>/urls.py</code> file to include the following line:</p> 
<pre class="prettyprint">
urlpatterns = patterns('',
    ...
    (r'^guestbook/', include('guestbook.urls')),
)</pre>
<p>Now, if you access any URL that starts with <code>/guestbook/</code>, the
system will look in the app-specific URL configuration file
<code>/guestbook/urls.py</code> to route the request.</p>
<h2>Creating the models</h2>
<p>Open your <code>/guestbook/models.py</code> file, and create this database
model:</p> 
<pre class="prettyprint">
from google.appengine.ext import db
from django.contrib.auth.models import User

class Greeting(db.Model):
    author = db.ReferenceProperty(User)
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)</pre>
<p>The user model will be provided for us by <code>app-engine-patch</code>, so
it does not have to be specified. Since we want Django and Google user
authentication at the same time, enable middleware in your settings and
specifying the correct user model. Replace Django's AuthenticationMiddleware
in <code>/settings.py</code>:</p>
<pre class="prettyprint">
# Replace Django's AuthenticationMiddleware with HybridAuthenticationMiddleware.
MIDDLEWARE_CLASSES = (
    ...
    'ragendja.auth.middleware.HybridAuthenticationMiddleware',
    ...
)</pre>
<p>and add</p>
<pre class="prettyprint">
# Change the User model class
AUTH_USER_MODULE = 'ragendja.auth.hybrid_models'

# Add google_login_url and google_logout_url tags
GLOBALTAGS = ('ragendja.templatetags.googletags',)</pre>
<p>to the end of the file.</p>
<p>That's all. No, really! Now you can use both Django and Google user
authentication. Furthermore, you have activated template tags that can be used
to render Google login and logout links in any template. To try it, create a
<code>/guestbook/templates/index.html</code> file with this content:</p> 
<pre class="prettyprint">
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="login"&gt;
  {% if user.is_authenticated %}
    Welcome, {{ user.username }}
    &lt;a href="{% google_logout_url request.get_full_path %}"&gt;Logout&lt;/a&gt;
  {% else %}
    &lt;a href="{% google_login_url request.get_full_path %}"&gt;Login&lt;/a&gt;
  {% endif %}
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>and set the URL-routing in <code>/guestbook/urls.py</code>:</p>
<pre class="prettyprint">
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'index.html'}),
)</pre>
<p>If you now load <code>http://localhost:8000/guestbook/</code> in your
browser, you will see Google authentication in action. Hard, wasn't it?</p>
<p class="note"><b>Note:</b> Here you also see one of Django's generic views
in action by rendering a HTML-template.</p>
<h2>Providing access for non-Google accounts</h2>
<p>Now let's add the authorization for people without a Google account. We
will again make use of generic views as much as possible, because using them
is easier and less error-prone than writing the views yourself.</p>
<p>The first thing is to enable users to sign up. Remember the
<code>AUTH_USER_MODULE</code> directive we set in <code>settings.py</code>? It
will perform some magic that allows us to import the normal Django User model
and still have the hybrid authentication support.</p>
<h2>Signing up users</h2>
<p>To let users sign up for an account, add the following code to
<code>/guestbook/views.py</code>:</p> 
<pre class="prettyprint">
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect

def create_new_user(request):
    form = UserCreationForm()
    # if form was submitted, bind form instance.
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            # user must be active for login to work
            user.is_active = True
            user.put()
            return HttpResponseRedirect('/guestbook/login/')
    return render_to_response('guestbook/user_create_form.html', {'form': form})
</pre>
<p>I won't go into much detail here, suffice it to say that this is nothing
else than standard Django. <code>app-engine-patch</code> handles the creation
of users behind the scenes, including using the App Engine datastore instead
of the normal database-tables used by Django.</p>
<p>The <code>UserCreationForm</code> is automatically supplied with Django.
This view creates a form object, and passes it to an HTML-template called
<code>user_create_form.html</code>. When a form is submitted and validated via
a <code>POST</code> request, a new user will be created, and the user will be
redirected to a login page. If the form is not valid, a meaningful error
message is rendered.</p>
<p>To see this in action, there are two small things left to do. First, hook
the "create_new_user" method into your URL-configuration in
<code>/guestbook/urls.py</code>:</p> 
<pre class="prettyprint">
urlpatterns = patterns('',
    ...
    (r'^signup/$', 'guestbook.views.create_new_user'),
)</pre>
<p>And create a template
<code>/guestbook/templates/user_create_form.html</code>:</p> 
<pre class="prettyprint">
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form action="." method="post"&gt;
  &lt;table&gt;
    {{form.as_table}}
  &lt;/table&gt;
  You can also login with your &lt;a href="{% google_login_url "/guestbook" %}"&gt;Google account.&lt;/a&gt;
  &lt;input type="submit" value="submit"&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h2>Logging in a Django user</h2>
<p>In case you hate reading long texts on the monitor as much as I do, I will
make this one quick. Just add this to your
<code>/guestbook/urls.py</code>:</p>
<pre class="prettyprint">
urlpatterns = patterns('',
    ...
    (r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'guestbook/user_create_form.html'}),
)</pre>
<p>Please note that I have reused the template for user creation to save you
from doing another copy &amp; paste. That's it. Create a new user or go to
<code>http://localhost:8000/guestbook/login/</code> to see this generic view
in action.</p>
<p class="note"><b>Note:</b> When not specified otherwise, the login generic
view will redirect to "/accounts/profile/" after successful login.  To change
this add <code>LOGIN_REDIRECT_URL = "/guestbook/"</code> to
<code>settings.py</code>, or logged in users will be greeted by a 404 message.</p>
<p>The Logout link that is displayed currently only logs out Google users. To
log out Django users, just include a generic view in your "/guestbook/urls.py"
like this:</p>
<pre class="prettyprint">
#the "logout" generic view expects a template logged_out.html. Using this generic view, you can redirect the user to
#another page after log out.
(r'^logout/$', 'django.contrib.auth.views.logout_then_login', {'login_url': '/guestbook/'}),
</pre>
<p>and replace the logout link in <code>/guestbook/templates/index.html</code> with:</p>
<pre class="prettyprint">
{% if user.is_active %} &lt;a href="/guestbook/logout"&gt; 
{% else %} &lt;a href="{% google_logout_url "/guestbook/" %}"&gt;
{% endif %}Logout&lt;/a&gt;
</pre>
<p>This works because Google users do not have the <code>is_active</code>
field set. There are better ways to check which type of user we are dealing
with, but this is simple and works for our case. The repository version of
<code>app-engine-patch</code> includes methods for differentiation
between user types.</p>
<h2>Getting the guestbook working</h2>
<p>Now let's add the ability to create and display guestbook entries. Add the
following to the end of <code>/guestbook/views.py</code>:</p>
<pre class="prettyprint">
from django.views.generic.list_detail import object_list
from django.views.generic.create_update import create_object
from django.contrib.auth.decorators import login_required
from guestbook.models import Greeting

def list_entries(request):
    return object_list(request, Greeting.all())

@login_required
def create_entry(request):
    # Add username to POST data, so it gets set in the created model
    # You could also use a hidden form field for example, but this is more secure
    request.POST = request.POST.copy()
    request.POST['author'] = str(request.user.key())
    return create_object(request, Greeting, post_save_redirect='/guestbook')
</pre>
<p>and change <code>/guestbook/urls.py</code> to:</p> 
<pre class="prettyprint">
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^$', 'guestbook.views.list_entries'),
    (r'^sign/$', 'guestbook.views.create_entry'),
    (r'^signup/$', 'guestbook.views.create_new_user'),
    (r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'guestbook/user_create_form.html'}),
    (r'^logout/$', 'django.contrib.auth.views.logout_then_login', {'login_url': '/guestbook/'}),
)
</pre>
<p>The generic views expect templates that you have to create
<code>/guestbook/templates/greeting_list.html</code>:</p> 
<pre class="prettyprint">
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="login"&gt;
  {% if user.is_authenticated %}
    Welcome, {{ user.username }}
    {% if user.is_active %}
      &lt;a href="/guestbook/logout"&gt;
    {% else %}
      &lt;a href="{% google_logout_url "/guestbook/" %}">
    {% endif %}Logout&lt;/a&gt;
  {% else %}
    &lt;a href="{% google_login_url request.get_full_path %}">Login with your Google account&lt;/a&gt;&lt;br&gt;
    &lt;a href="/guestbook/login">Login with your normal account&lt;/a&gt;&lt;br&gt;
    &lt;a href="/guestbook/signup"&gt;Sign up&lt;/a&gt;&lt;br&gt;
  {% endif %}
&lt;/div&gt;
{% for object in object_list %}
  &lt;p&gt;{{object.author.username}}: {{object.content}}&lt;/p&gt;
{% endfor %}
&lt;a href="/guestbook/sign/"&gt;Add entry&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>and <code>/guestbook/templates/greeting_form.html</code>:</p> 
<pre class="prettyprint">
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form method="POST" action="."&gt;
  {{form.content}}
  &lt;input type="submit" value="create"&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Signing the guestbook now works. We have replaced the generic view that
rendered <code>index.html</code> for the URL <code>/guestbook/</code> by a
reference to the function that shows the list of entries. The
<code>login_required</code> decorator provided by Django ensures that a user
has to be logged in to access the view in question. By default, the decorator
expects the login URL to be located at <code>/accounts/login/</code> to change
this modify your <code>settings.py</code> file with:</p>
<pre class="prettyprint">
LOGIN_URL = '/guestbook/login'
</pre>
<p class="note"><b>Note:</b> If we wanted anonymous users to be able to sign
the guestbook, we would have to take care of the fact that anonymous users
don't have a key-attribute.</p>
<h2>Conclusion</h2>
<p>We now have a (very) basic project that allows users to sign in both with
Google and non-Google accounts, and to add entries to a guestbook. We have
made extensive use of generic views, to demonstrate how they can make common
tasks a lot easier. If this was your first encounter with Django on App
Engine, I hope that this article is enough to get you started. If you already
are a proficient Django user, I hope we made it interesting for you!</p>

<h3>About the Author...</h3>

<div style="float: left; padding-bottom: 5px; padding-right: 5px;">
<a href="http://profile.ak.facebook.com/v230/437/62/s795684099_2864.jpg"><img src="img/jesaja.png" alt="Jesaja Everling" style="border: 1px solid black;" height="55" width="55"></a>
</div>

<p>Jesaja Everling lives in the former capital of Germany, Bonn. Having
started to learn Python not much more than two years ago, Jesaja was amazed
when he learned that he could use his now favorite programming language for
web-development. After deciding to try out Django, he never looked back. He
had the luck that the company he is working for during his studies of
Technical Journalism needed somebody that would get deep down and dirty with
Django development.</p>
<p>Being a self-declared early adopter of Google products, he was excited when
he heard of App Engine, and started using it as soon as he could. When looking
at a computer screen and not working or studying, he tries to get the hang out
of using the Datastore, or hangs around in the appengine channel on IRC and
swears at his timezone that is constantly making him miss all the interesting
discussions.</p>
</div>
</div>


   
      </div><!-- end gc-pagecontent -->
   </div><!-- end gooey wrapper -->

    </div> <!-- end codesite content -->

<div id="gc-footer" dir="ltr">
  <div class="text">
    
      <div class="notice"><div id="notice" style="text-align: center; border: 1em 0em 1em 0em">
  Except as otherwise <a
  href="http://code.google.com/policies.html#restrictions">noted</a>,
  the content of this page is licensed under the <a rel="license"
  href="http://creativecommons.org/licenses/by/2.5/">Creative Commons
  Attribution 2.5 License</a>, and code samples are licensed under the
  <a rel="license" href="http://www.apache.org/licenses/LICENSE-2.0">Apache
  2.0 License</a>.
<!-- <rdf:RDF xmlns="http://web.resource.org/cc/" 
              xmlns:dc="http://purl.org/dc/elements/1.1/"
              xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <Work rdf:about="">
    <license rdf:resource="http://creativecommons.org/licenses/by/2.5/" />
  </Work>
  <License rdf:about="http://creativecommons.org/licenses/by/2.5/">
    <permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
    <permits rdf:resource="http://web.resource.org/cc/Distribution"/>
    <requires rdf:resource="http://web.resource.org/cc/Notice"/>
    <requires rdf:resource="http://web.resource.org/cc/Attribution"/>
    <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
  </License>
</rdf:RDF> -->
</div>
Java is a registered trademark of Sun Microsystems, Inc.</div>
    
    &copy;2009 Google -
    <a href="http://code.google.com">Code Home</a> -
    <a href="http://www.google.com/accounts/TOS">Terms of Service</a> -
    <a href="http://www.google.com/privacy.html">Privacy Policy</a> -
    <a href="http://code.google.com/more">Site Directory</a>
    <br /> <br />
    Google Code offered in:
    <a href="http://code.google.com/intl/en">English</a> -
    <a href="http://code.google.com/intl/es">Español</a> -
    <a href="http://code.google.com/intl/ja">日本語</a> -
    <a href="http://code.google.com/intl/ko">한국어</a> -
    <a href="http://code.google.com/intl/pt-BR">Português</a> -
    <a href="http://code.google.com/intl/ru">Pусский</a> -
    <a href="http://code.google.com/intl/zh-CN">中文(简体)</a> -
    <a href="http://code.google.com/intl/zh-TW">中文(繁體)</a>
  </div>
</div><!-- end gc-footer -->

</div><!-- end gc-containter -->

<script type="text/javascript">CODESITE_CSITimer['load'].tick('ats');</script>
<script src="../../js/codesite_tail.pack.04102009.js" type="text/javascript"></script>






  </body>
</html>


